package com.yifi.common.utils;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.jfinal.plugin.activerecord.Record;

import cn.hutool.core.util.IdUtil;

public class JWTUtils {

	private static final Logger logger = Logger.getLogger(JWTUtils.class);  
	/**
     * token秘钥，请勿泄露，请勿随便修改 backups:JKKLJOoadsafa
     */
    public static final String SECRET = "yifisoft";

    /**
     * token 过期时间: 10天
     */
    public static final int calendarField = Calendar.DATE;
    public static final int calendarInterval = 10;

    /**
     * JWT生成Token.<br/>
     * <p>
     * JWT构成: header, payload, signature
     *
     * @param user_id 登录成功后用户user_id, 参数user_id不可传空
     */
    public static String createToken(String user_id) throws Exception {
        Date iatDate = new Date();
        // expire time
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(calendarField, calendarInterval);
        Date expiresDate = nowTime.getTime();

        // header Map
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        // build token
        // param backups {iss:Service, aud:APP}
        String token = JWT.create().withHeader(map) // header
                .withClaim("iss", "Service") // payload
                .withClaim("aud", "APP")
                .withClaim("user_id", null == user_id ? null : user_id.toString())
                .withIssuedAt(iatDate) // sign time
                .withExpiresAt(expiresDate) // expire time
                .sign(Algorithm.HMAC256(SECRET)); // signature

        return token;
    }
    
    public static String createToken(Record rec) throws Exception {
        Date iatDate = new Date();
        // expire time
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(calendarField, calendarInterval);
        Date expiresDate = nowTime.getTime();

        // header Map
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        // build token
        // param backups {iss:Service, aud:APP}
        String token = JWT.create().withHeader(map) // header
                .withClaim("id",IdUtil.fastUUID()) // payload
                .withClaim("iss", "Service") // payload
                .withClaim("aud", "APP")
                .withClaim("ccode", rec.getStr("ccode"))
                .withClaim("cname", rec.getStr("cname"))
                .withClaim("user_num", rec.getStr("user_num"))
                .withClaim("cdept", rec.getStr("cdept"))
                .withClaim("cwork_dept", rec.getStr("cwork_dept"))
                .withClaim("c_pro", rec.getStr("c_pro"))
                .withIssuedAt(iatDate) // sign time
                .withExpiresAt(expiresDate) // expire time
                .sign(Algorithm.HMAC256(SECRET)); // signature

        return token;
    }

    /**
     * 解密Token
     * @param token
     * @return
     * @throws Exception
     */
    public static Map<String, Claim> verifyToken(String token) {
        DecodedJWT jwt = null;
        
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        jwt = verifier.verify(token);
        
        return jwt.getClaims();
    }


    /**
     * 换取用户ccode
     * @param token
     * @return
     */
    public static String getAppUID(String token) {
        Map<String, Claim> claims = verifyToken(token);
        Claim user_id_claim = claims.get("ccode");
        if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
            // token 校验失败, 抛出Token验证非法异常
        }
        return user_id_claim.asString();
    }

    /**
     * 根据Col值获取数据
     * @param token
     * @param col
     * @return
     */
    public static String getUserByCol(String token,String col) {
        Map<String, Claim> claims = verifyToken(token);
        Claim user_id_claim = claims.get(col);
        if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
            // token 校验失败, 抛出Token验证非法异常
        }
        return user_id_claim.asString();
    }
    /**
     * 换取Map链接
     * @param token
     * @return
     */
    public static Map<String, Claim> getUserClaim(String token)
    {
    	Map<String, Claim> claims = verifyToken(token);
    	return claims;
    }
    
    
    
    public static void main(String[] args) {
		
    	try {
			System.out.println(createToken("admin"));

			System.out.println("----------------------");
			
			System.out.println(getAppUID("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJBUFAiLCJ1c2VyX2lkIjoiYWRtaW4iLCJpc3MiOiJTZXJ2aWNlIiwiZXhwIjoxNTgwMTk1NTE2LCJpYXQiOjE1NzkzMzE1MTZ9.VbWpXprwd9Kk_TSaw-RZBcX6fS7wJDJlQeMXX-eUAEE"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    
    
    /**
     * 	外部调用生成token的有效期限
     * @param loginCode
     * @param loginPwd
     * @return
     * @throws Exception
     */
    public static String createToken(String loginCode,String loginPwd) throws Exception {
        
        return createToken(loginCode,loginPwd,"");
    }
    
    /**
     * 	外部调用生成token的有效期限
     * @param loginCode
     * @param loginPwd
     * @return
     * @throws Exception
     */
    public static String createToken(String loginCode,String loginPwd,String param) throws Exception {
        Date iatDate = new Date();
        // expire time
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.HOUR,12);		//12小时有效期
        Date expiresDate = nowTime.getTime();

        // header Map
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        // build token
        // param backups {iss:Service, aud:APP}
        String token = JWT.create().withHeader(map) // header
                .withClaim("id",IdUtil.fastUUID()) // payload
                .withClaim("iss", "Service") 		// payload
                .withClaim("aud", "API")
                .withClaim("company", "yifisoft")
                .withClaim("loginCode",loginCode)
                .withClaim("loginPwd",loginPwd)
                .withClaim("param",param)
                .withIssuedAt(iatDate) 				// sign time
                .withExpiresAt(expiresDate) 		// expire time
                .sign(Algorithm.HMAC256(SECRET)); 	// signature

        return token;
    }
}
